#ifndef __MY_LOG__
#define __MY_LOG__

#include <iostream>
// struct tm{};
#include <time.h>
// va_list
#include <stdarg.h>
// open();
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <unistd.h>
#include <stdlib.h>

namespace Log
{
#define SIZE 1024

// 信息类别
#define INFO 0
#define DEBUG 1
#define WARNING 2
#define LOGERROR 3
#define FATAL 4

// 输出目的地
#define SCREEN 1
#define LOGFILE 2   //./log.txt
#define Classfile 3 //./log.txt.debug

// 日志文件
#define LogFile "log.txt"
    class MyLog
    {
    private:
        int _printMethod; // 输出方法
        std::string path;

    public:
        MyLog()
        {
            _printMethod = LOGFILE;
            path = "./";
        }

        // 信息等级由int到string
        std::string levelToString(int level)
        {
            switch (level)
            {
            case INFO:
                return "Info";
            case DEBUG:
                return "Debug";
            case WARNING:
                return "Warning";
            case LOGERROR:
                return "Error";
            case FATAL:
                return "Fatal";
            default:
                return "None";
            }
        }

        /*log.logmyssage();
        void logmessage(int level, const char *format, ...)
            {
                time_t t = time(nullptr);
                struct tm *ctime = localtime(&t);
                char leftbuffer[SIZE];
                snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),
                         ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
                         ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

                va_list s;
                va_start(s, format);
                char rightbuffer[SIZE];
                vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
                va_end(s);

                // 格式：默认部分+自定义部分
                char logtxt[SIZE * 2];
                snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);

                // printf("%s", logtxt);
                printLog(level, logtxt);
            }
        */
        // log(Warning, "accept error, %s: %d", strerror(errno), errno);
        void operator()(int level, const char *msg_format, ...)
        {
            // 构建日志内容 打印到指定处

            time_t timestamp = time(nullptr);
            struct tm *ctime = localtime(&timestamp);
            // level+年月日
            char leftbuffer[SIZE];
            snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),
                     ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
                     ctime->tm_hour, ctime->tm_min, ctime->tm_sec);
            // %s %d %s %s __FILE__, __LINE__,  __DATE__,__TIME__
            // log.hpp 103 Aug 16 2024 18:14:54

            // 自定义msg
            va_list arg_list;               // 存储可变参数列表信息
            va_start(arg_list, msg_format); // 初始化 使其指向函数参数列表中format参数之后的第一个可变参数
            char rightbuffer[SIZE];
            // s: safe v: 输出到字符串缓冲区
            vsnprintf(rightbuffer, sizeof(rightbuffer), msg_format, arg_list);
            va_end(arg_list); // 清理va_list变量

            // 格式：默认部分+自定义部分
            char log_content[SIZE * 2];
            snprintf(log_content, sizeof(log_content), "%s %s", leftbuffer, rightbuffer);

            // printf("%s", log_content); // debug

            // 调用printLog printLog根据当前printMethod 输出到指定处
            printLog(_printMethod, level, log_content);
        }

        void Enable(int method)
        {
            _printMethod = method;
        }

        void printLog(int printMethod, int level, const std::string &log_content)
        {
            switch (printMethod)
            {
            case SCREEN:
                std::cout << log_content << std::endl;
                break;
            case LOGFILE:
                printOneFile(LogFile, log_content);
                break;
            case Classfile:
                printClassFile(level, log_content);
                break;
            default:
                break;
            }
        }

        // 输出到普通文件 ./"log.txt"
        void printOneFile(const std::string &log_filename, const std::string &log_content)
        {
            // path = "./"; #define LogFile "log.txt"
            std::string _logFilename = path + log_filename;
            // 0666：所有用户都可读写但不可执行
            int fd = open(_logFilename.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666); // "log.txt"
            if (fd < 0)
                return;

            std::string logMsg = log_content;
            logMsg += "\n";
            write(fd, logMsg.c_str(), logMsg.size());
            close(fd);
        }

        // 输出到类别文件 "log.txt.Debug"
        void printClassFile(int level, const std::string &log_content)
        {
            // #define LogFile "log.txt"
            std::string filename = LogFile;
            filename += ".";
            filename += levelToString(level); // "log.txt.Debug"
            printOneFile(filename, log_content);
        }

        ~MyLog()
        {
        }
    };

    MyLog log;

    /*va_list用法展示
    printf("hello %d, hello %s, hello %c, hello %d,", 1, "hello", 'c', 123);
    int sum(int n, ...)
    {
        va_list s; // char*
        va_start(s, n);

        int sum = 0;
        while(n)
        {
            sum += va_arg(s, int);
            n--;
        }

        va_end(s); //s = NULL
        return sum;
    }
    */
};
#endif //__MY_LOG__
